package demoMod.anm2editor.ui;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import demoMod.anm2editor.enums.LayerType;
import demoMod.anm2editor.fonts.FontKeys;
import demoMod.anm2editor.localization.LocalizedStrings;
import demoMod.anm2editor.model.*;
import demoMod.anm2editor.utils.IdGenerator;
import demoMod.gdxform.abstracts.Container;
import demoMod.gdxform.core.FormManager;
import demoMod.gdxform.helpers.FontHelper;
import demoMod.gdxform.interfaces.Element;
import demoMod.gdxform.interfaces.MouseEventSubscriber;
import demoMod.gdxform.ui.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class TrackInfoItem implements Element, MouseEventSubscriber {
    private Container<? extends Element> parent;
    private String id = "";
    private final Track track;
    private final Timeline timeline;
    private final GLabel trackName;
    private final GLabel useSpriteSheetId;
    private Color bg;
    private final Texture bgTexture;
    private boolean solo = false;

    public TrackInfoItem(float width, float height, Track track, BitmapFont trackNameFont, BitmapFont spriteSheetFont) {
        this.track = track;
        this.timeline = (Timeline) FormManager.getInstance().getContainerById(Timeline.ID);
        this.trackName = new GLabel(0, trackNameFont.getLineHeight() / 2.0F, width, height, trackNameFont);
        this.trackName.setColor(Color.WHITE.cpy());
        this.trackName.setText(track.getName());
        this.useSpriteSheetId = new GLabel(0, spriteSheetFont.getLineHeight() / 2.0F, width, height, spriteSheetFont);
        this.useSpriteSheetId.setColor(Color.DARK_GRAY.cpy());
        this.useSpriteSheetId.setText(Integer.toString(track.getSpriteSheetId()));
        if (this.track.getLayerType() == LayerType.NULL) {
            bg = Color.PINK.cpy();
            bg.a = 0.9F;
        } else {
            bg = new Color(0.16863F, 0.16863F, 0.16863F, 0.9F);
        }
        Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        pixmap.setColor(bg);
        pixmap.fill();
        bgTexture = new Texture(pixmap);
    }

    public Track getTrack() {
        return track;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

    @Override
    public void update() {

    }

    @Override
    public void render(SpriteBatch sb) {
        sb.setColor(Color.WHITE.cpy());
        if (this.bgTexture != null) {
            TrackContent trackContent = track.getContent(Project.currentProject.getCurrentAnimation().getName());
            if (!trackContent.isVisible()) {
                sb.setColor(Color.GRAY);
            }
            sb.draw(this.bgTexture, getX(true), getY(true), getWidth(), getHeight());
        }
        this.trackName.setX(getX(true) + 5.0F);
        this.trackName.setY(getY(true) + this.trackName.getFont().getLineHeight() / 2.0F);
        this.useSpriteSheetId.setX(getX(true) + Gdx.graphics.getWidth() * 0.15F);
        if (this.track.getLayerType() == LayerType.LAYER) {
            this.useSpriteSheetId.setY(getY(true) + this.useSpriteSheetId.getFont().getLineHeight() / 2.0F);
        }
        this.trackName.render(sb);
        this.useSpriteSheetId.render(sb);
    }

    @Override
    public Container<? extends Element> getParent() {
        return this.parent;
    }

    @Override
    public void setParent(Container<? extends Element> parent) {
        this.parent = parent;
    }

    @Override
    public float getX(boolean isAbsolute) {
        return getParent() != null ? getParent().getX(isAbsolute) : 0;
    }

    @Override
    public float getY(boolean isAbsolute) {
        return getParent() != null ? getParent().getY(isAbsolute) : 0;
    }

    @Override
    public void setX(float x) {

    }

    @Override
    public void setY(float y) {

    }

    @Override
    public float getWidth() {
        return getParent() != null ? getParent().getWidth() : Gdx.graphics.getWidth();
    }

    @Override
    public float getHeight() {
        return getParent() != null ? getParent().getHeight() : Gdx.graphics.getHeight();
    }

    @Override
    public void setWidth(float width) {

    }

    @Override
    public void setHeight(float height) {

    }

    @Override
    public Color getBackground() {
        return this.bg;
    }

    @Override
    public void setBackground(Color background) {
        this.bg = background;
    }

    @Override
    public boolean isResizable() {
        return false;
    }

    @Override
    public void setResizable(boolean resizable) {

    }

    @Override
    public boolean enabled() {
        return false;
    }

    @Override
    public void setEnabled(boolean enabled) {

    }

    @Override
    public boolean visible() {
        return true;
    }

    @Override
    public void setVisible(boolean visible) {

    }

    @Override
    public void dispose() {
        this.trackName.dispose();
        this.useSpriteSheetId.dispose();
        if (this.bgTexture != null) {
            this.bgTexture.dispose();
        }
    }

    @Override
    public boolean clickDown(int screenX, int screenY, int button) {
        if (screenX > getX(true) && screenX < getX(true) + getWidth() && Gdx.graphics.getHeight() - screenY > getY(true)
                && Gdx.graphics.getHeight() - screenY < getY(true) + getHeight()) {
            int index = ((TrackInfoList) getParent().getParent()).indexOf(this);
            if (button == Input.Buttons.RIGHT) {
                GMenuList menuList = new GMenuList();
                menuList.setWidth(200.0F);
                menuList.setX(screenX);
                menuList.setY(Gdx.graphics.getHeight() - screenY);

                List<String> strings = LocalizedStrings.getStrings("TrackInfoItem");
                GMenuItem newTrack = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(0) + "...", FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        TextInputWindow textInputWindow = new TextInputWindow(strings.get(1), "", FontHelper.getFont(FontKeys.SIM_HEI_14));
                        textInputWindow.setConfirmCallback(text -> {
                            List<String> options = new ArrayList<>();
                            options.add(strings.get(2));
                            options.add(strings.get(3));
                            OptionWindow optionWindow = new OptionWindow(strings.get(4), options, FontHelper.getFont(FontKeys.SIM_HEI_14));
                            String animationName = Project.currentProject.getCurrentAnimation().getName();
                            optionWindow.setConfirmCallback(i -> {
                                Track track;
                                switch (i) {
                                    case 0:
                                    default:
                                        track = new Track(LayerType.LAYER);
                                        break;
                                    case 1:
                                        track = new Track(LayerType.NULL);
                                        break;
                                }
                                track.setName(text);
                                track.setId(track.getLayerType() == LayerType.LAYER ? IdGenerator.nextTrackId() : IdGenerator.nextNullId());
                                track.setSpriteSheetId(0);
                                for (Animation animation : Project.currentProject.getAnimations()) {
                                    track.addContent(animation.getName(), new TrackContent().setKeyFrames(new ArrayList<>()));
                                }
                                TrackContentItem contentItem = new TrackContentItem(animationName, track);
                                TrackInfoItem infoItem = addTrack(track, contentItem);
                                Operation operation = new Operation() {
                                    @Override
                                    public void undo() {
                                        Project.currentProject.getTracks().remove(track);
                                        ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).removeItem(infoItem);
                                        timeline.removeTrack(track);
                                        if (track.getLayerType() == LayerType.LAYER) {
                                            IdGenerator.setTrackId(track.getId());
                                        } else if (track.getLayerType() == LayerType.NULL) {
                                            IdGenerator.setNullId(track.getId());
                                        }
                                        GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                                        if (scrollPane.getPlainHeight() - Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight() > 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                                            float plainHeight = scrollPane.getPlainHeight() - 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight();
                                            if (plainHeight < FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2) {
                                                plainHeight = FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2;
                                            }
                                            scrollPane.setPlainHeight(plainHeight);
                                            timeline.getScrollPane().setPlainHeight(plainHeight);
                                            int len = StatusBar.getMaxAnimationLength();
                                            if (len > 120) {
                                                timeline.getScrollPane().setPlainWidth((len + 50) * timeline.getCellWidth());
                                            } else {
                                                timeline.getScrollPane().setPlainWidth(120 * timeline.getCellWidth());
                                            }
                                        }
                                    }

                                    @Override
                                    public void redo() {
                                        Project.currentProject.getTracks().add(index + 1, track);
                                        ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(index, infoItem);
                                        timeline.getTrackContentList().addItem(index, contentItem);
                                        if (track.getLayerType() == LayerType.LAYER) {
                                            IdGenerator.setTrackId(track.getId() + 1);
                                        } else if (track.getLayerType() == LayerType.NULL) {
                                            IdGenerator.setNullId(track.getId() + 1);
                                        }
                                        GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                                        if (scrollPane.getPlainHeight() < Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                                            scrollPane.setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                            timeline.getScrollPane().setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                        }
                                    }
                                };
                                operation.setName(strings.get(5));
                                ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                            });
                        });
                    }

                    private TrackInfoItem addTrack(Track track, TrackContentItem trackContentItem) {
                        Project.currentProject.getTracks().add(index + 1, track);
                        TrackInfoItem ret = new TrackInfoItem(TrackInfoItem.this.getWidth(), TrackInfoItem.this.getHeight(), track, trackName.getFont(), useSpriteSheetId.getFont());
                        ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(index, ret);
                        timeline.getTrackContentList().addItem(index, trackContentItem);
                        GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                        if (scrollPane.getPlainHeight() < Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                            scrollPane.setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                            timeline.getScrollPane().setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                        }
                        return ret;
                    }
                };
                GMenuItem rename = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(6) + "...", FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        TextInputWindow textInputWindow = new TextInputWindow(strings.get(7), TrackInfoItem.this.track.getName(), FontHelper.getFont(FontKeys.SIM_HEI_14));
                        textInputWindow.setConfirmCallback(text -> {
                            String beforeName = TrackInfoItem.this.track.getName();
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    TrackInfoItem.this.trackName.setText(beforeName);
                                    TrackInfoItem.this.track.setName(beforeName);
                                }

                                @Override
                                public void redo() {
                                    TrackInfoItem.this.trackName.setText(text);
                                    TrackInfoItem.this.track.setName(text);
                                }
                            };
                            operation.setName(strings.get(8));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                            TrackInfoItem.this.trackName.setText(text);
                            TrackInfoItem.this.track.setName(text);
                        });
                    }
                };
                GMenuItem delete = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(9), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        deleteTrack();
                        String animationName = Project.currentProject.getCurrentAnimation().getName();
                        Operation operation = new Operation() {
                            @Override
                            public void undo() {
                                Project.currentProject.getTracks().add(index, track);
                                ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().addItem(index - 1, TrackInfoItem.this);
                                timeline.addTrack(animationName, track, index - 1);
                                GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                                if (scrollPane.getPlainHeight() < Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                                    scrollPane.setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                    timeline.getScrollPane().setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                }
                            }

                            @Override
                            public void redo() {
                                deleteTrack();
                            }
                        };
                        operation.setName(strings.get(10));
                        ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                    }

                    private void deleteTrack() {
                        Project.currentProject.getTracks().remove(track);
                        ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).removeItem(TrackInfoItem.this);
                        timeline.removeTrack(track);
                        GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                        if (scrollPane.getPlainHeight() - Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight() > 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                            float plainHeight = scrollPane.getPlainHeight() - 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight();
                            if (plainHeight < FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2) {
                                plainHeight = FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2;
                            }
                            scrollPane.setPlainHeight(plainHeight);
                            timeline.getScrollPane().setPlainHeight(plainHeight);
                            int len = StatusBar.getMaxAnimationLength();
                            if (len > 120) {
                                timeline.getScrollPane().setPlainWidth((len + 50) * timeline.getCellWidth());
                            } else {
                                timeline.getScrollPane().setPlainWidth(120 * timeline.getCellWidth());
                            }
                        }
                    }
                };
                GMenuItem changeSprite = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(11) + "...", FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        List<String> options = Project.currentProject.getSpriteSheetIds().stream().map(Object::toString).collect(Collectors.toList());
                        int index = options.indexOf(useSpriteSheetId.getText());
                        OptionWindow optionWindow = new OptionWindow(strings.get(12), options, FontHelper.getFont(FontKeys.SIM_HEI_14), Math.max(index, 0));
                        optionWindow.setConfirmCallback(i -> {
                            int changeBefore = track.getSpriteSheetId();
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    track.setSpriteSheetId(changeBefore);
                                    useSpriteSheetId.setText(Integer.toString(changeBefore));
                                }

                                @Override
                                public void redo() {
                                    track.setSpriteSheetId(Integer.parseInt(options.get(i)));
                                    useSpriteSheetId.setText(options.get(i));
                                }
                            };
                            track.setSpriteSheetId(Integer.parseInt(options.get(i)));
                            useSpriteSheetId.setText(options.get(i));
                            operation.setName(strings.get(13));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        });
                    }
                };
                if (track.getLayerType() == LayerType.NULL) {
                    changeSprite.setEnabled(false);
                }
                String animationName = Project.currentProject.getCurrentAnimation().getName();
                TrackContent trackContent = track.getContent(animationName);
                GMenuItem muteTrack = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), trackContent.isVisible() ? strings.get(14) : strings.get(15), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        TrackContent trackContent = track.getContent(animationName);
                        trackContent.setVisible(!trackContent.isVisible());
                        Operation operation = new Operation() {
                            @Override
                            public void undo() {
                                trackContent.setVisible(!trackContent.isVisible());
                            }

                            @Override
                            public void redo() {
                                trackContent.setVisible(!trackContent.isVisible());
                            }
                        };
                        operation.setName(trackContent.isVisible() ? strings.get(16) : strings.get(17));
                        ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                    }
                };
                GMenuItem soloTrack = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), !solo ? strings.get(18) : strings.get(19), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        for (Track track : Project.currentProject.getTracks()) {
                            if (track != TrackInfoItem.this.track) {
                                track.getContent(Project.currentProject.getCurrentAnimation().getName()).setVisible(solo);
                            }
                        }
                        solo = !solo;
                        trackContent.setVisible(true);
                    }
                };
                GMenuItem moveTrack = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(20), FontHelper.getFont(FontKeys.SIM_HEI_14));
                moveTrack.setSubMenu(() -> {
                    GMenuList moveTrackMenu = new GMenuList();
                    moveTrackMenu.setWidth(200.0F);
                    GMenuItem moveUp = new GMenuItem(moveTrackMenu.getWidth(), moveTrackMenu.getMenuItemHeight(), strings.get(21), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                        @Override
                        public void onClick() {
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index - 1);
                            timeline.swapTrack(index, index - 1);
                            Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index - 1);
                                    timeline.swapTrack(index, index - 1);
                                    Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                                }

                                @Override
                                public void redo() {
                                    ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index - 1);
                                    timeline.swapTrack(index, index - 1);
                                    Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                                }
                            };
                            operation.setName(strings.get(22));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        }

                        @Override
                        public boolean isHotKeyPressed() {
                            return Gdx.input.isKeyPressed(Input.Keys.U);
                        }
                    };
                    if (index == 0) moveUp.setEnabled(false);
                    GMenuItem moveDown = new GMenuItem(moveTrackMenu.getWidth(), moveTrackMenu.getMenuItemHeight(), strings.get(23), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                        @Override
                        public void onClick() {
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index + 1);
                            timeline.swapTrack(index, index + 1);
                            Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index + 1);
                                    timeline.swapTrack(index, index - 1);
                                    Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                                }

                                @Override
                                public void redo() {
                                    ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).swap(index, index + 1);
                                    timeline.swapTrack(index, index - 1);
                                    Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                                }
                            };
                            operation.setName(strings.get(24));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        }

                        @Override
                        public boolean isHotKeyPressed() {
                            return Gdx.input.isKeyPressed(Input.Keys.D);
                        }
                    };
                    if (index == ((TrackInfoList) getParent().getParent()).getElements().size() - 1) moveDown.setEnabled(false);
                    GMenuItem moveToTop = new GMenuItem(moveTrackMenu.getWidth(), moveTrackMenu.getMenuItemHeight(), strings.get(25), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                        @Override
                        public void onClick() {
                            addToTop();
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().removeItem(TrackInfoItem.this);
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().addItem(index - 1, TrackInfoItem.this);
                                    TrackContentItem trackContentItem = timeline.getTrackContentList().getItem(0);
                                    timeline.removeTrack(track);
                                    timeline.getTrackContentList().addItem(index - 1, trackContentItem);
                                    Project.currentProject.getTracks().add(index, Project.currentProject.getTracks().remove(0));
                                }

                                @Override
                                public void redo() {
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().removeItem(TrackInfoItem.this);
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().addItem(-1, TrackInfoItem.this);
                                    TrackContentItem trackContentItem = timeline.getTrackContentList().getItem(index);
                                    timeline.removeTrack(track);
                                    timeline.getTrackContentList().addItem(-1, trackContentItem);
                                    Project.currentProject.getTracks().add(0, Project.currentProject.getTracks().remove(index));
                                }
                            };
                            operation.setName(strings.get(26));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        }

                        private void addToTop() {
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).removeItem(TrackInfoItem.this);
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(-1, TrackInfoItem.this);
                            timeline.removeTrack(track);
                            timeline.addTrack(Project.currentProject.getCurrentAnimation().getName(), track, -1);
                            Project.currentProject.getTracks().add(0, Project.currentProject.getTracks().remove(index));
                        }

                        @Override
                        public boolean isHotKeyPressed() {
                            return Gdx.input.isKeyPressed(Input.Keys.T);
                        }
                    };
                    if (index == 0) moveToTop.setEnabled(false);
                    GMenuItem moveToBottom = new GMenuItem(moveTrackMenu.getWidth(), moveTrackMenu.getMenuItemHeight(), strings.get(27), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                        @Override
                        public void onClick() {
                            addToBottom();
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().removeItem(TrackInfoItem.this);
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().addItem(index - 1, TrackInfoItem.this);
                                    TrackContentItem trackContentItem = timeline.getTrackContentList().getItem(timeline.getTrackContentList().getElements().size() - 1);
                                    timeline.removeTrack(track);
                                    timeline.getTrackContentList().addItem(index - 1, trackContentItem);
                                    Project.currentProject.getTracks().add(index, Project.currentProject.getTracks().remove(Project.currentProject.getTracks().size() - 1));
                                }

                                @Override
                                public void redo() {
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().removeItem(TrackInfoItem.this);
                                    ((TrackPane)FormManager.getInstance().getContainerById(TrackPane.ID)).getTrackInfoList().addItem(TrackInfoItem.this);
                                    timeline.removeTrack(track);
                                    TrackContentItem trackContentItem = timeline.getTrackContentList().getItem(index);
                                    timeline.getTrackContentList().addItem(trackContentItem);
                                    Project.currentProject.getTracks().add(Project.currentProject.getTracks().remove(index));
                                }
                            };
                            operation.setName(strings.get(28));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        }

                        private void addToBottom() {
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).removeItem(TrackInfoItem.this);
                            ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(TrackInfoItem.this);
                            timeline.removeTrack(track);
                            timeline.addTrack(Project.currentProject.getCurrentAnimation().getName(), track);
                            Project.currentProject.getTracks().add(Project.currentProject.getTracks().remove(index));
                        }

                        @Override
                        public boolean isHotKeyPressed() {
                            return Gdx.input.isKeyPressed(Input.Keys.B);
                        }
                    };
                    if (index == ((TrackInfoList) getParent().getParent()).getElements().size() - 1) moveToBottom.setEnabled(false);
                    moveToBottom.setSplitLine(false);
                    moveTrackMenu.addElement(moveUp);
                    moveTrackMenu.addElement(moveDown);
                    moveTrackMenu.addElement(moveToTop);
                    moveTrackMenu.addElement(moveToBottom);

                    return moveTrackMenu;
                });
                GMenuItem copyTrack = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(29), FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        Track track = new Track(TrackInfoItem.this.track.getLayerType());
                        track.setName(TrackInfoItem.this.trackName.getText());
                        track.setId(track.getLayerType() == LayerType.LAYER ? IdGenerator.nextTrackId() : IdGenerator.nextNullId());
                        track.setSpriteSheetId(TrackInfoItem.this.track.getSpriteSheetId());
                        for (Animation animation : Project.currentProject.getAnimations()) {
                            List<KeyFrame> keyFrames = new ArrayList<>();
                            TrackInfoItem.this.track.getContent(animation.getName()).getKeyFrames().forEach(keyFrame -> keyFrames.add(keyFrame.makeCopy()));
                            track.addContent(animation.getName(), new TrackContent().setKeyFrames(keyFrames));
                        }
                        TrackContentItem contentItem = new TrackContentItem(animationName, track);
                        TrackInfoItem infoItem = addTrack(track, contentItem);
                        Operation operation = new Operation() {
                            @Override
                            public void undo() {
                                Project.currentProject.getTracks().remove(track);
                                ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).removeItem(infoItem);
                                timeline.removeTrack(track);
                                if (track.getLayerType() == LayerType.LAYER) {
                                    IdGenerator.setTrackId(track.getId());
                                } else if (track.getLayerType() == LayerType.NULL) {
                                    IdGenerator.setNullId(track.getId());
                                }
                                GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                                if (scrollPane.getPlainHeight() - Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight() > 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                                    float plainHeight = scrollPane.getPlainHeight() - 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight();
                                    if (plainHeight < FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2) {
                                        plainHeight = FormManager.getInstance().getContainerById(Timeline.ID).getHeight() * 2;
                                    }
                                    scrollPane.setPlainHeight(plainHeight);
                                    timeline.getScrollPane().setPlainHeight(plainHeight);
                                    int len = StatusBar.getMaxAnimationLength();
                                    if (len > 120) {
                                        timeline.getScrollPane().setPlainWidth((len + 50) * timeline.getCellWidth());
                                    } else {
                                        timeline.getScrollPane().setPlainWidth(120 * timeline.getCellWidth());
                                    }
                                }
                            }

                            @Override
                            public void redo() {
                                Project.currentProject.getTracks().add(index + 1, track);
                                ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(index, infoItem);
                                timeline.getTrackContentList().addItem(index, contentItem);
                                if (track.getLayerType() == LayerType.LAYER) {
                                    IdGenerator.setTrackId(track.getId() + 1);
                                } else if (track.getLayerType() == LayerType.NULL) {
                                    IdGenerator.setNullId(track.getId() + 1);
                                }
                                GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                                if (scrollPane.getPlainHeight() < Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                                    scrollPane.setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                    timeline.getScrollPane().setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                                }
                            }
                        };
                        operation.setName(strings.get(29));
                        ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                    }

                    private TrackInfoItem addTrack(Track track, TrackContentItem trackContentItem) {
                        Project.currentProject.getTracks().add(index + 1, track);
                        TrackInfoItem ret = new TrackInfoItem(TrackInfoItem.this.getWidth(), TrackInfoItem.this.getHeight(), track, trackName.getFont(), useSpriteSheetId.getFont());
                        ((TrackInfoList) TrackInfoItem.this.getParent().getParent()).addItem(index, ret);
                        timeline.getTrackContentList().addItem(index, trackContentItem);
                        GScrollPane scrollPane = ((TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID)).getScrollPane();
                        if (scrollPane.getPlainHeight() < Project.currentProject.getTracks().size() * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight()) {
                            scrollPane.setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                            timeline.getScrollPane().setPlainHeight(scrollPane.getPlainHeight() + 3 * ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
                        }
                        return ret;
                    }
                };
                copyTrack.setSplitLine(false);
                menuList.addElement(newTrack);
                menuList.addElement(rename);
                menuList.addElement(delete);
                menuList.addElement(changeSprite);
                menuList.addElement(muteTrack);
                menuList.addElement(soloTrack);
                menuList.addElement(moveTrack);
                menuList.addElement(copyTrack);
                FormManager.getInstance().addContainer(menuList);
                FormManager.getInstance().moveToTop(menuList);
            }
            if (getParent() != null && getParent().getParent() instanceof TrackInfoList && !((GList.ListCellRenderer<TrackInfoItem>) getParent()).isSelected()) {
                timeline.selectTrack(index);
            }
            return true;
        }
        return false;
    }

    public GLabel getTrackName() {
        return trackName;
    }

    @Override
    public boolean clickUp(int screenX, int screenY, int button) {
        return false;
    }

    @Override
    public boolean mouseDragged(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        TrackPane trackPane = (TrackPane) FormManager.getInstance().getContainerById(TrackPane.ID);
        TrackInfoList trackInfoList = trackPane.getTrackInfoList();
        if ((float)Gdx.input.getX() >= this.getX(true) && (float)Gdx.input.getX() <= this.getX(true) + this.getWidth() && (float)(Gdx.graphics.getHeight() - Gdx.input.getY()) >= this.getY(true) && (float)(Gdx.graphics.getHeight() - Gdx.input.getY()) <= this.getY(true) + this.getHeight()) {
            if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)) {
                int index = trackInfoList.indexOf(this);
                if (amount > 0 && index < trackInfoList.getElements().size() - 1 || amount < 0 && index > 0) {
                    List<String> strings = LocalizedStrings.getStrings("TrackInfoItem");
                    if (amount > 0) {
                        trackInfoList.swap(index, index + 1);
                        timeline.swapTrack(index, index + 1);
                        Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                        Operation operation = new Operation() {
                            @Override
                            public void undo() {
                                trackInfoList.swap(index, index + 1);
                                timeline.swapTrack(index, index + 1);
                                Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                            }

                            @Override
                            public void redo() {
                                trackInfoList.swap(index, index + 1);
                                timeline.swapTrack(index, index + 1);
                                Collections.swap(Project.currentProject.getTracks(), index, index + 1);
                            }
                        };
                        operation.setName(strings.get(24));
                        ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                    } else {
                        trackInfoList.swap(index, index - 1);
                        timeline.swapTrack(index, index - 1);
                        Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                        Operation operation = new Operation() {
                            @Override
                            public void undo() {
                                trackInfoList.swap(index, index - 1);
                                timeline.swapTrack(index, index - 1);
                                Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                            }

                            @Override
                            public void redo() {
                                trackInfoList.swap(index, index - 1);
                                timeline.swapTrack(index, index - 1);
                                Collections.swap(Project.currentProject.getTracks(), index, index - 1);
                            }
                        };
                        operation.setName(strings.get(22));
                        ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                    }
                    Gdx.input.setCursorPosition(Gdx.input.getX(), Gdx.input.getY() + (int) trackInfoList.getCellHeight() * amount);
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean moveToElementBorder(Element element) {
        return false;
    }
}
